#include "Graphics.h"

Graphics::Graphics() : m_pD3D9(NULL), m_pDevice(NULL), m_antialising(false), m_vertexProcessing(D3DCREATE_SOFTWARE_VERTEXPROCESSING) {}

void Graphics::Release() {
	SAFE_RELEASE(m_pDevice);
	SAFE_RELEASE(m_pD3D9);
}

bool Graphics::Initialize(HWND hWnd) {
	m_hWnd = hWnd;
	SAFE_RELEASE(m_pD3D9);
	SAFE_RELEASE(m_pDevice);
	m_pD3D9 = Direct3DCreate9(D3D_SDK_VERSION);
	if(!m_pD3D9) {
		SHOWERROR("Direct3DCreate9() - Failed", __FILE__, __LINE__);
		return false;
	}

	m_pD3D9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &m_displayMode);
	m_pD3D9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &m_caps);

	// check for hardware T&L
	DWORD m_vertexProcessing = 0;
	if(m_caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) {
		m_vertexProcessing = D3DCREATE_HARDWARE_VERTEXPROCESSING;
		_cprintf("Hardware T&L [Enabled]\n");
		// check for pure device
		/*if(m_caps.DevCaps & D3DDEVCAPS_PUREDEVICE) {
			m_vertexProcessing |= D3DCREATE_PUREDEVICE;
			_cprintf("Hardware T&L - Pure Device [Enabled]\n");
		} else {
			_cprintf("Hardware T&L [Enabled]\n");
		}*/
	} else {
		m_vertexProcessing = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
		_cprintf("Hardware T&L [Disabled]\n");
	}

	if(!BuildPresentParameters()) {
		SAFE_RELEASE(m_pD3D9);
		_cprintf("Error with BuildPresentParameters(): Releasing m_pD3D9...\n");
		return false;
	}

	_cprintf("Creating Device...");
	HRESULT hresult;
	// create the device
	hresult = m_pD3D9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd, m_vertexProcessing, &m_pp, &m_pDevice);
	if(FAILED(hresult)) {
		SAFE_RELEASE(m_pD3D9);
		SHOWERROR("CreateDevice() - Failed", __FILE__, __LINE__);
		return false;
	}
	_cprintf("Device Created!\n");
	
	return true;
}

bool Graphics::BuildPresentParameters() {
	ZeroMemory(&m_pp, sizeof(m_pp));
	D3DFORMAT adapterFormat = m_displayMode.Format;
	if(SUCCEEDED(m_pD3D9->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, 
		D3DRTYPE_SURFACE, D3DFMT_D24S8))) {
		m_pp.AutoDepthStencilFormat = D3DFMT_D24S8;
		_cprintf("Auto-Depth Stencil Format [D3DFMT_D24S8]\n");
    } else if(SUCCEEDED(m_pD3D9->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, 
		D3DRTYPE_SURFACE, D3DFMT_D24X8))) {
		m_pp.AutoDepthStencilFormat = D3DFMT_D24X8;
		_cprintf("Auto-Depth Stencil Format [D3DFMT_D24X8]\n");
	} else if(SUCCEEDED(m_pD3D9->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, adapterFormat, D3DUSAGE_DEPTHSTENCIL, 
		D3DRTYPE_SURFACE, D3DFMT_D16))) {
		m_pp.AutoDepthStencilFormat = D3DFMT_D16;
		_cprintf("Auto-Depth Stencil Format [D3DFMT_D16]\n");
	} else {
		SHOWERROR("Unable to set depth format", __FILE__, __LINE__);
		return false;
	}

	m_pp.Windowed					= TRUE;
    m_pp.SwapEffect					= D3DSWAPEFFECT_DISCARD;
    m_pp.BackBufferFormat			= D3DFMT_UNKNOWN;
	m_pp.BackBufferCount			= 1;
	m_pp.BackBufferHeight			= m_displayMode.Height;
	m_pp.BackBufferWidth			= m_displayMode.Width;
	m_pp.hDeviceWindow				= m_hWnd;
	//m_pp.EnableAutoDepthStencil		= TRUE;		// wont work!!! (enabled in WorldEditor, z-buffer still doesn't work...

	if(m_antialising /*&& m_vertexProcessing != D3DCREATE_SOFTWARE_VERTEXPROCESSING*/) {
		DWORD total;
		if(SUCCEEDED(m_pD3D9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
														m_pp.AutoDepthStencilFormat, true,
														D3DMULTISAMPLE_NONMASKABLE,
														&total))) {
			m_pp.MultiSampleType = D3DMULTISAMPLE_NONMASKABLE;
			m_pp.MultiSampleQuality = total-1;
			_cprintf("Antialising [ON]: x%i\n", m_pp.MultiSampleQuality);
		} else {
			MessageBox(NULL, "Unable to antialise.\nAttempting to revert...", "ERROR", MB_OK);
			m_pp.MultiSampleType = D3DMULTISAMPLE_NONE;
			m_pp.MultiSampleQuality = 0;
			m_antialising = false;
		}
	} else {
		_cprintf("Antialising [OFF]\n");
	}

	//m_surface = NULL;

	//HRESULT hr = m_pD3D9->CheckDepthStencilMatch(0, D3DDEVTYPE_HAL, m_displayMode.Format, m_displayMode.Format, m_displayMode.Format);
	//		if (FAILED(hr))
	//		{
	//			PRINT("CheckDepthStencilMatch");
	//			//return 0;
	//		}


	//m_pDevice->CreateRenderTarget(m_pp.BackBufferWidth,
	//							m_pp.BackBufferHeight,
	//							m_pp.AutoDepthStencilFormat,
	//							m_pp.MultiSampleType,
	//							m_pp.MultiSampleQuality,
	//							true,
	//							&m_surface,
	//							NULL);

	//m_pDevice->CreateDepthStencilSurface(m_pp.BackBufferWidth,
	//									m_pp.BackBufferHeight,
	//									m_pp.AutoDepthStencilFormat,
	//									m_pp.MultiSampleType,
	//									m_pp.MultiSampleQuality,
	//									true,
	//									&m_surface,
	//									NULL);

	//m_pDevice->SetDepthStencilSurface(m_surface);

	return true;
}

BOOL Graphics::Reset() {
	if(m_pDevice) {
		if (!BuildPresentParameters())
			return FALSE;
		m_pDevice->Reset(&m_pp);
	}

	return TRUE;
}

void Graphics::setAntiAlising(bool aa) {
	m_antialising = aa;
}